/*
 *  Variable.cpp
 *  ddltool
 *
 *  Created by John David Duncan on 5/11/09.
 *  Copyright 2009 Sun Microsystems. All rights reserved.
 *
 */
/*
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; version 2 of the License.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */

#include "Parser.h"

/* externs */
extern int action_id;

/* statics */
static const char *mode_options[] =  { "run" , "dump" , "test" , 0 } ;
static const int mode_values[] = { EXE_RUN , EXE_DUMP , EXE_TEST };
Variable var_mode(mode_options, mode_values);

static const char *bool_options[] = { "0","no","NO","1","yes","YES",0 };
static const int   bool_values[]  = { 0,0,0,1,1,1 };
Variable var_bool(bool_options, bool_values);

int show_sys_cols = 0;

char * all_tool_variables[] = { "mode" , "hidden" , "db" , 0 };

/* Use the ib_vars.map file to initialize an array: */
#define IB_VAR(x) x ,
char * all_innodb_variables[] = {
#include "ib_vars.map" 
0 };
#undef IB_VAR


/* function prototypes */
int show_ib_var(char *);
int show_user_var(char *);
int show_all_vars(SQLnode *);

int set_user_var(SQLnode *);
int set_ib_var(SQLnode *);


/* implementations */

int Variable::set(int *dest, char *str) {
  for(int i = 0; options[i] ; i++) {
    if(! strcmp(str, options[i])) {
      *dest = values[i];
      return DB_SUCCESS;
    }
  }  
  return e_VAR_BAD_VALUE;
}


const char * Variable::show(int source) {
  for(int i = 0; ; i++)
    if(source == values[i])
      return options[i];

  return "[undefined]";
}


int show_var(SQLnode *node) {
  char *schema;
  if(! (node->sch || node->obj))
    return show_all_vars(node);

  if(node->sch) schema = node->sch;

  else return e_VAR_SCH_UNKNOWN;

  if(!strcmp(schema, "ib")) 
    return show_ib_var(node->obj);
  else if (!strcmp(schema, "tool")) 
    return show_user_var(node->obj);
  
  return e_VAR_SCH_UNKNOWN;
}


int set_var(SQLnode *node) {
  char *schema;
  if(node->sch) schema = node->sch;
  else return e_VAR_SCH_UNKNOWN;
  
  if(!strcmp(node->sch,"tool"))
    return set_user_var(node);
  else if(!strcmp(node->sch, "ib"))
    return set_ib_var(node);
  
  return e_VAR_SCH_UNKNOWN;
}


int show_ib_var(char *name) {
  ib_cfg_type_t var_type;
  union {
    ib_bool_t       bool_val;
    ib_ulint_t      ulint_val;
    unsigned long   ulong_val;
    char *          text_val;
    ib_cb_t         callback_val;
  } cf_val; 
  
  if(ib_cfg_var_get_type(name, &var_type)) {
    ib_cfg_get(name, &cf_val);
    printf("ib.%s = ",name);
    switch(var_type) {
      case IB_CFG_IBOOL:
        printf("%s\n", cf_val.bool_val ? "true" : "false");   break;
      case IB_CFG_ULINT:
        printf("%lu\n", cf_val.ulint_val);                    break;
      case IB_CFG_ULONG:
        printf("%lu\n", cf_val.ulong_val);                    break;
      case IB_CFG_TEXT:
        printf("%s\n",  cf_val.text_val);                     break;
      case IB_CFG_CB:
        printf("callback: (%p)\n", cf_val.callback_val);      break;
      default:
        printf("weird type [%d]\n", var_type);
        return e_VAR_IB_TYPE_UNKNOWN;
    }
    return DB_SUCCESS;
  }
 return e_VAR_OBJ_UNKNOWN;         
}


int set_ib_var(SQLnode *node) {
  ib_cfg_type_t var_type;
  int multiplier = 1;
  int err = DB_SUCCESS;
  int ival = 0;
  
  if(node->flags.is_scaled) {
    size_t vlen = strlen(node->value);
    char c = node->value[vlen - 1];
    switch(c) {
      case 'k': case 'K':
        multiplier = 1024 ;               break;
      case 'm': case 'M':
        multiplier = 1024 * 1024;         break;
      case 'g': case 'G':
        multiplier = 1024 * 1024 * 1024;  break;
    }
    node->value[vlen - 1] = 0;
  }

  if(ib_cfg_var_get_type(node->obj, &var_type)) {
    switch(var_type) {
      case IB_CFG_IBOOL:
        err = var_bool.set(&ival, node->value);
        if(err != DB_SUCCESS) return err;
        if(ival) err = ib_cfg_set(node->obj, IB_TRUE);
        else err = ib_cfg_set(node->obj, IB_FALSE);
        break;
      case IB_CFG_ULINT:
      case IB_CFG_ULONG:
        ival = atoi(node->value) * multiplier;
        err = ib_cfg_set(node->obj, ival);
        break;      
      case IB_CFG_TEXT:
        err = ib_cfg_set(node->obj, node->value);
        break;
      case IB_CFG_CB:  
        err = e_NO_SET_CALLBACK;
        break;
      default:
        return e_VAR_IB_TYPE_UNKNOWN;
    }
    return err;
  }
  return e_VAR_OBJ_UNKNOWN;         
}


int show_user_var(char *name) {
  if(!strcmp(name,"mode"))
    printf("tool.mode = %s\n", var_mode.show(action_id));
  else if(!strcmp(name,"db")) 
    printf("tool.db = %s\n", default_db);
  else if(!strcmp(name,"hidden"))
    printf("tool.hidden = %d\n",show_sys_cols);
  else return e_VAR_OBJ_UNKNOWN;

  return DB_SUCCESS;
}


int set_user_var(SQLnode *node) {
  if(!strcmp(node->obj,"mode"))
    return var_mode.set(&action_id, node->value);
  else if(!strcmp(node->obj,"db")) {
    default_db = node->value;
    return DB_SUCCESS;
  }
  else if(!strcmp(node->obj,"hidden"))
    return var_bool.set(&show_sys_cols, node->value);
  
  return e_VAR_OBJ_UNKNOWN;
}


int show_all_vars(SQLnode *node) {
  int i;
  
  for(i = 0 ; all_innodb_variables[i] ; i++) 
    show_ib_var(all_innodb_variables[i]);
  
  printf("\n");
  for(i = 0 ; all_tool_variables[i] ; i++)
    show_user_var(all_tool_variables[i]);
  
  return DB_SUCCESS;
}


